"""Time dimension model"""
import datetime, exceptions, logging
from sqlalchemy import *
from sqlalchemy.orm import *

from digvcs.model.meta import Base

class HourSubDim(Base):
    __tablename__ = 'sd_hours'
    id    = Column(Integer, primary_key=True)
    value = Column(Integer, CheckConstraint('value BETWEEN 0 AND 23'), nullable=False, unique=True)

    def __init__(self, value):
        self.value = value

    def __repr__(self):
        return "<HourSubDim(value=%s)>" % self.value

class MinuteSubDim(Base):
    __tablename__ = 'sd_minutes'
    id    = Column(Integer, primary_key=True)
    value = Column(Integer, CheckConstraint('value BETWEEN 0 AND 59'), nullable=False, unique=True)

    def __init__(self, value):
        self.value = value

    def __repr__(self):
        return "<MinuteSubDim(value=%s)>" % self.value

class SecondSubDim(Base):
    __tablename__ = 'sd_seconds'
    id    = Column(Integer, primary_key=True)
    value = Column(Integer, CheckConstraint('value BETWEEN 0 AND 59'), nullable=False, unique=True)

    def __init__(self, value):
        self.value = value

    def __repr__(self):
        return "<SecondSubDim(value=%s)>" % self.value

class TimeDim(Base):
    __tablename__ = 'd_times'

    id   = Column(Integer, primary_key=True)
    time = Column(Time, nullable=False, unique=True)

    hour_id   = Column(Integer, ForeignKey('sd_hours.id'), nullable=False)
    hour      = relation(HourSubDim, backref=backref('times'))

    minute_id = Column(Integer, ForeignKey('sd_minutes.id'), nullable=False)
    minute    = relation(MinuteSubDim, backref=backref('times'))

    second_id = Column(Integer, ForeignKey('sd_seconds.id'), nullable=False)
    second    = relation(SecondSubDim, backref=backref('times'))

    def __init__(self, hour, minute, second):
        self.time   = datetime.time(hour.value, minute.value, second.value)
        self.hour   = hour
        self.minute = minute
        self.second = second

    def __repr__(self):
        return "<TimeDim(%s:%s:%s)>" % (self.hour.value, self.minute.value, self.second.value)

d_times_table = TimeDim.__table__
d_times_table.append_constraint(UniqueConstraint('hour_id', 'minute_id', 'second_id'))

def import_time_dimension(session):
    """Imports time dimension data into DB using given non-transactional Session object.
    Takes a longer while, it loads 24 HourSubDim, 60 MinuteSubDim, 60 SecondSubDim and 86400 (24*60*60) TimeDim objects.
    """
    if session is None:
        raise exceptions.AttributeError('Session must be provided')

    logging.info('Preparing time dimension')

    hours   = map(lambda x: HourSubDim(x), range(0,24))
    minutes = map(lambda x: MinuteSubDim(x), range(0,60))
    seconds = map(lambda x: SecondSubDim(x), range(0,60))

    session.add_all(hours)
    session.add_all(minutes)
    session.add_all(seconds)
    session.flush()

    for h in hours:
        times = list()
        for m in minutes:
            for s in seconds:
                times.append(TimeDim(h,m,s))
        session.add_all(times)
        session.flush()
        logging.debug('Finished hour %s of %s' % (h.value+1, len(hours)))

    logging.info('Finished time dimension')
